using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using WP.Commons;
using WP.DB;
using WP.Controls;
using WP.Modules;
using WP.MF.DataAccess;

namespace WP.MF.Form
{
    public partial class frmMUserMenuMtn : BaseQryRpt
    {

        #region Define Variable
        private const int intLineHeight = 16;  // tvEdit a text line height
        private string mstrSaveName = string.Empty;
        private string mstrDragSource = string.Empty;
        private bool mblnChange = false;
        private bool mblnCut = false;
        private int mintPicdownIndex = 0;
        private string mstrDragNodeKey = string.Empty;
        private InsertNodePos mInsertNodePos;

        private enum InsertNodePos
        {
            NodeStart = 0,
            NodePrev,
            NodeSelf,
            NodeNext,
            NodeEnd,
            NodeNoPos
        }

        #endregion

        #region Constructor Func && public Func
        public frmMUserMenuMtn()
        {
            InitializeComponent();
            LoadAllControl(new ArrayList(this.Controls));
        }
        public void ShowForm()
        {
            //this.MdiParent = SysVar.MDIParentForm;
            this.ShowDialog();
        }
        #endregion

        #region ***Form Events
        private void frmMUserMenuMtn_Load(object sender, EventArgs e)
        {
            this.Text = DataFunctions.GetMsg(this.Name, "MSG_UserMenuMtns"); //this.CurrentMenuInfo.strMenuName;
            Create_tvOption();
        }
        private void btnUpdate_Click(object sender, EventArgs e)
        {
            WP.MF.DataAccess.MUserMenuDAL mDal = new MUserMenuDAL();
            string strCurKey = string.Empty;

            pnlOption.Visible = false;
            if (tvEdit.Nodes.Count == 0)
            {
                if (mstrSaveName == string.Empty)
                    btnSaveAs_Click(this.btnSaveAs, new EventArgs());
                else
                    DeleteUserMenu();

                return;
            }

            if (mstrSaveName == string.Empty)
                btnSaveAs_Click(this.btnSaveAs, new EventArgs());
            else
                mDal.UpdateUserMenu(tvEdit, mstrSaveName);
        }
        private void btnSaveAs_Click(object sender, EventArgs e)
        {
            WP.MF.DataAccess.MUserMenuDAL mDal = new MUserMenuDAL();

            pnlOption.Visible = false;
            frmInput finput = new frmInput();
            mstrSaveName = finput.InputData("Menu Name", "Save as", "", "", "", "", true);
            if (mstrSaveName == "%NONE%") return;
            if (mstrSaveName.Trim() != string.Empty)
            {
                if (tvEdit.Nodes.Count == 0)
                {
                    DeleteUserMenu();
                    return;
                }
                txtEdit.Text = mstrSaveName;
                mDal.UpdateUserMenu(tvEdit, mstrSaveName);
                Create_tvOption();
            }
        }
        private void btnOK_Click(object sender, EventArgs e)
        {
            TreeNode nodeX = null;
            int intCheck = 0;
            string strCheck = string.Empty;

            nodeX = FirstNode(GetOptionTreeView());  //GetOptionTreeView().Nodes[0];
            while (nodeX != null)
            {
                if (nodeX.Checked)
                {
                    strCheck = nodeX.Text;
                    intCheck+= 1;
                }
                nodeX = nodeX.NextNode;
            }
            
            if (intCheck == 0) return;
            pnlOption.Visible = false;
            this.Refresh();
            
            if (mintPicdownIndex == 0)
                Create_TreeView(tvStyle);
            else
            {
                if (mblnChange)
                {
                    switch (MsgBoxEx.Show(DataFunctions.GetMsg(this.Name, "MSG_UserDefinedMenuHasChanged"), DataFunctions.GetMsg(this.Name, "MSG_UserDefinedMenu"), MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation))
                    {
                        case DialogResult.Yes:
                            btnUpdate_Click(this.btnUpdate, new EventArgs());
                            break;
                        case DialogResult.No:
                            mblnChange = false;
                            break;
                        case DialogResult.Cancel:
                            return;
                    }
                }
                
                Create_TreeView(tvEdit);
                if (intCheck != 1)
                    mstrSaveName = "";
                else
                    mstrSaveName = strCheck;
            }
            
            if (intCheck == 1)
                GetStyleEditControl().Text = strCheck;
            else
                GetStyleEditControl().Text = "More Option";
        }
        private void btnClear_Click(object sender, EventArgs e)
        {
            TreeNode nodeX = null;
            nodeX = FirstNode(GetOptionTreeView());
            while (nodeX != null)
            {
                nodeX.Checked = false;
                nodeX = nodeX.NextNode;
            }
        }
        private void btnSelectAll_Click(object sender, EventArgs e)
        {
            TreeNode nodeX = null;
            nodeX = FirstNode(GetOptionTreeView());//(mintPicdownIndex);
            while (nodeX != null)
            {
                if (Chk_ItemCanbeChecked(nodeX.Name.ToString()))
                    nodeX.Checked = true;

                nodeX = nodeX.NextNode;
            }
        }
        private void btnDelete_Click(object sender, EventArgs e)
        {
            bool blnDel = false;
            TreeNode nodeX = null;
            WP.MF.DataAccess.MUserMenuDAL mDal = new MUserMenuDAL();

            nodeX = FirstNode(GetOptionTreeView());
            while (nodeX != null)
            {
                if (nodeX.Checked)
                {
                    blnDel = true;
                    break;
                }
                nodeX = nodeX.NextNode;
            }
            if (!blnDel) return;

            if (MsgBoxEx.Show(DataFunctions.GetMsg(this.Name, "MSG_DeleteSelectedMenuEntries"), DataFunctions.GetMsg(this.Name, "MSG_Delete"), MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.No) return;
            nodeX = FirstNode(GetOptionTreeView());
            while (nodeX != null)
            {
                if (nodeX.Checked)
                {
                    mDal.DelUsermenu(nodeX.Text);
                    if (nodeX.Text == txtEdit.Text)
                    {
                        mstrSaveName = string.Empty;
                        mblnChange = false;
                        txtEdit.Text = string.Empty;
                        tvEdit.Nodes.Clear();
                    }
                }
                nodeX = nodeX.NextNode;
            }
            Create_tvOption();
        }
        private void ubt_Click(object sender, EventArgs e)
        {
            // set pnlOption visable and position
            Control con = sender as Control;
            if (con == null) return;
            int iIndex = 0;

            if (con.Name == ubtStyle.Name)
            {
                tvOption0.Visible = true;
                tvOption1.Visible = false;
                btnSelectAll.Visible = true;
                btnClear.Visible = true;
                btnDelete.Visible = false;
            }
            else
            {
                tvOption1.Visible = true;
                tvOption0.Visible = false;
                btnSelectAll.Visible = false;
                btnClear.Visible = false;
                btnDelete.Visible = true;
            }

            if (con.Name == ubtStyle.Name)
                iIndex = 0;
            else
                iIndex = 1;

            if (mintPicdownIndex == iIndex)
                pnlOption.Visible = !pnlOption.Visible;
            else
            {
                pnlOption.Visible = true;
                mintPicdownIndex = iIndex;
            }

            if (iIndex == 0)
                pnlOption.Left = txtStyle.Left;// + ubtStyle.Width - pnlOption.Width + 60;
            else
                pnlOption.Left = txtEdit.Left;
        }
        private void btnExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        private void btnHelp_Click(object sender, EventArgs e)
        {
            base.OnHelp();
        }

        private void tvEdit_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
        {
            if (e.Data.GetDataPresent(typeof(TreeNode)))
            {
                e.Effect = DragDropEffects.Move;
            }
        }
        private void tvEdit_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
        {
            string strKey = string.Empty;
            TreeNode dragNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
            tvEdit.SelectedNode = tvEdit.HitTest(e.X, e.Y).Node;
            if (mstrDragSource != "STYLE") mstrDragSource = "EDIT";
            if (dragNode == null)
            {
                mstrDragNodeKey = string.Empty;
            }
            else
            {
                mstrDragNodeKey = dragNode.Name;
                if (strKey != mstrDragNodeKey)
                {
                    strKey = mstrDragNodeKey;
                }
            }
        }
        private void tvEdit_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
        {
            if (e.Effect == DragDropEffects.Move)
            {
                TreeView tv = sender as TreeView;
                TreeNode dragNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
                mInsertNodePos = GetInsertPos(dragNode, e.X, e.Y);
                if (mstrDragSource == "STYLE")               // drag source is tvStyle
                {
                    ////if Shift = 1 Then       // Shift is down
                    ////    Add_DragDropTree(dragNode, 1);      // only copy select item
                    ////else if Not popmnuNode.Checked Then
                    ////    Add_DragDropTree(dragNode, 1);      // only copy select item
                    ////else
                        Add_DragDropTree(dragNode, 0);      // copy all , include all sons
                }
                else
                    Order_DragDropTree(dragNode);           // drag source is tvEdit self

                tvEdit.SelectedNode = null;
                mstrDragSource = "";

            }
        }
        private void tvEdit_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (pnlOption.Visible)
                pnlOption.Visible = false;

            tvEdit.SelectedNode = tvEdit.HitTest(e.X, e.Y).Node;
            if (e.Button == MouseButtons.Right)
            {
                tmiCut.Enabled = (tvEdit.SelectedNode == null ? false : true);
                tmiCopy.Enabled = (tvEdit.SelectedNode == null ? false : true);
                tmiDelete.Enabled = (tvEdit.SelectedNode == null ? false : true);
                tmiPaste.Enabled = (tvPaste.Nodes.Count == 0 ? false : true);
                tmiDeleteAll.Enabled = (tvEdit.Nodes.Count == 0 ? false : true);
            }
        }
        private void tvStyle_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)
        {
            tvStyle.DoDragDrop(e.Item, DragDropEffects.Move);
        }
        private void tvStyle_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
        {
            mstrDragSource = "STYLE";
        }
        private void tvStyle_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
        {
            mstrDragSource = "";
        }
        private void tvStyle_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (pnlOption.Visible)
                pnlOption.Visible = false;

            tvStyle.SelectedNode = tvStyle.HitTest(e.X, e.Y).Node;
            if (e.Button == MouseButtons.Right)
            {
                tmiCut.Enabled = false;
                tmiCopy.Enabled = (tvStyle.SelectedNode == null ? false : true);
                tmiPaste.Enabled = false;
                tmiDelete.Enabled = false;
                tmiDeleteAll.Enabled = false;
            }
        }
        private void tvOption_AfterCheck(object sender, System.Windows.Forms.TreeViewEventArgs e)
        {
            TreeNode nodeX = null;
            GetOptionTreeView().SelectedNode = e.Node;
            if (!e.Node.Checked) return;
            if (GetOptionTreeView() == tvOption1)
            {
                nodeX = FirstNode(tvOption1);
                while (nodeX != null)
                {
                    if (nodeX.Name != e.Node.Name)
                        nodeX.Checked = false;

                    nodeX = nodeX.NextNode;
                }
            }
        }

        private void tmiFunc_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem tmi = sender as ToolStripMenuItem;
            if (tmi == null) return;

            if (tmi.Name == tmiCut.Name)
            {
                if (tvPaste.Nodes.Count > 0) tvPaste.Nodes.Clear();
                CopyTreeToTree(tvEdit, tvEdit.SelectedNode, CurNodeLastSon(tvEdit, tvEdit.SelectedNode), tvPaste, null, string.Empty);
                tvEdit.Nodes.Remove(tvEdit.SelectedNode);
                mblnCut = true;
            }
            else if (tmi.Name == tmiCopy.Name)
            {
                if (tvPaste.Nodes.Count > 0) tvPaste.Nodes.Clear();
                if (this.ActiveControl.Name == tvStyle.Name)
                {
                    if (tmiIncludeChildNode.Checked)
                        CopyTreeToTree(tvStyle, tvStyle.SelectedNode, CurNodeLastSon(tvStyle, tvStyle.SelectedNode), tvPaste, null, GetNodeCopyNo(tvEdit, tvStyle.SelectedNode.Name));
                    else
                        CopyTreeToTree(tvStyle, tvStyle.SelectedNode, tvStyle.SelectedNode, tvPaste, null, GetNodeCopyNo(tvEdit, tvStyle.SelectedNode.Name));
                }
                else
                    CopyTreeToTree(tvEdit, tvEdit.SelectedNode, CurNodeLastSon(tvEdit, tvEdit.SelectedNode), tvPaste, null, GetNodeCopyNo(tvEdit, tvEdit.SelectedNode.Name));
            }
            else if (tmi.Name == tmiDelete.Name)
            {
                if (tvEdit.SelectedNode == null) return;
                tvEdit.Nodes.Remove(tvEdit.SelectedNode);
                mblnChange = true;
            }
            else if (tmi.Name == tmiPaste.Name)
            {
                if (tvEdit.SelectedNode == null)     // add in end
                    CopyTreeToTree(tvPaste, FirstNode(tvPaste), LastNode(tvPaste), tvEdit, null, GetNodeCopyNo(tvEdit, FirstNode(tvPaste).Name));
                else    // add in one node slef
                {
                    if (ChkParent(FirstNode(tvPaste), tvEdit.SelectedNode))
                        CopyTreeToTree(tvPaste, FirstNode(tvPaste), LastNode(tvPaste), tvEdit, tvEdit.SelectedNode, GetNodeCopyNo(tvEdit, FirstNode(tvPaste).Name));
                    else
                        MsgBoxEx.Show(DataFunctions.GetMsg(this.Name, "MSG_CanNotDoThis"), SysVar.WarnTitle);
                }
                if (mblnCut)
                {
                    mblnCut = false;
                    tvPaste.Nodes.Clear();
                }
            }
            else if (tmi.Name == tmiDeleteAll.Name)
            {
                if (tvEdit.Nodes.Count > 0) tvEdit.Nodes.Clear();
            }
            else if (tmi.Name == tmiIncludeChildNode.Name)
            {
                tmiIncludeChildNode.Checked = !tmiIncludeChildNode.Checked;
            }
        }

        #endregion

        #region ***Form Functions
        private void Create_tvOption()
        {
            int i = 0;
            int j = 0;
            string strSql = string.Empty;
            string strKey = string.Empty;
            DataTable dtMenu = null;
            DataRow drMenu = null;

            tvOption0.ImageList = this.iglMenu;
            tvOption1.ImageList = this.iglMenu;
            
            if (tvOption0.Nodes.Count > 0) tvOption0.Nodes.Clear();
            if (tvOption1.Nodes.Count > 0) tvOption1.Nodes.Clear();

            if (SysVar.MenuGLPermit) tvOption0.Nodes.Add("DefaultGL", "General Ledger", 0, 0);
            if (SysVar.MenuAPPermit) tvOption0.Nodes.Add("DefaultAP", "Accounts Payable", 1, 1);
            if (SysVar.MenuARPermit) tvOption0.Nodes.Add("DefaultAR", "Accounts Receivable", 2, 2);
            if (SysVar.MenuOEPermit) tvOption0.Nodes.Add("DefaultOE", "Customer Order Processing", 3, 3);
            if (SysVar.MenuIMPermit) tvOption0.Nodes.Add("DefaultIM", "Inventory Management", 4, 4);
            if (SysVar.MenuPOPermit) tvOption0.Nodes.Add("DefaultPO", "Purchasing and Receiving", 5, 5);
            if (SysVar.MenuRMPermit) tvOption0.Nodes.Add("DefaultRM", "Remanufacturing and Bill of Materials", 6, 6);
            if (SysVar.MenuTWPermit) tvOption0.Nodes.Add("DefaultTW", "Trader Worksheets", 7, 7);
            if (SysVar.MenuTPPermit) tvOption0.Nodes.Add("DefaultTP", "Transportation", 8, 8);
            if (SysVar.MenuESPermit) tvOption0.Nodes.Add("DefaultES", "Executive Summary", 9, 9);
            if (SysVar.MenuMFPermit) tvOption0.Nodes.Add("DefaultMF", "Management Functions", 10, 10);

            DBAccess dBAccess = new DBAccess(false, false);
            strSql = "select distinct UserMenuNo,UserMenuName from mUserMenu where UserName='" + SysVar.UserName + "' order by UserMenuNo";
            dtMenu = dBAccess.GetDataTable(strSql);
            for (i = 0; i<= 1; i++)
            {
                for (j=0; j< dtMenu.Rows.Count; j++)
                {
                    drMenu = dtMenu.Rows[j];
                    strKey = "UserMenu" + CvtFunc.ToString(drMenu["UserMenuNo"].ToString());
                    if (i == 0)
                        tvOption0.Nodes.Add(strKey, drMenu["UserMenuName"].ToString(), 12, 12);
                    else
                        tvOption1.Nodes.Add(strKey, drMenu["UserMenuName"].ToString(), 12, 12);
                }
            }
        }
        private void Create_TreeView(TreeView tvObject)
        {
            // Function: Create tree in tvStyle or in tvEdit
            int intTotal = 0;
            TreeNode nodeSel = null;
            TreeNode nodX = null;
            string strMenuSql = string.Empty;
            string strUserMenuSql = string.Empty;
            string strGroup = string.Empty;
            string strKey = string.Empty;
            string strSql = string.Empty;
            DBAccess dBAccess = new DBAccess(false, false);
            DataRow drGroup = null;
            DataTable dtMenu = null;
            DataTable dtUserMenu = null;
            DataView dvMenu = null;

            tvObject.ImageList = this.iglMenu;
            if (tvObject.Nodes.Count > 0) tvObject.Nodes.Clear();
            
            strSql = "select glSecurGrp,apSecurGrp,arSecurGrp,oeSecurGrp,imSecurGrp,poSecurGrp,rmSecurGrp,twSecurGrp,";
            strSql+= "tpSecurGrp,smSecurGrp,mfSecurGrp from mUser where UserName='" + SysVar.UserName + "'";
            drGroup = dBAccess.GetDataFirstRow(strSql);

            nodeSel = FirstNode(GetOptionTreeView()); //GetOptionTreeView().TopNode;
            while (nodeSel != null)
            {
                if (nodeSel.Checked)
                {
                    switch (nodeSel.Name.ToString().Substring(nodeSel.Name.ToString().Length - 2))  // because key like "Default??"
                    {
                        case "GL":
                            strGroup = string.Format("{0:00}", CvtFunc.ToInt(drGroup["glSecurGrp"]));
                            strMenuSql+= " or (MenuID like '" + ModuleInfo.StrModule.GL + "' and Permit" + strGroup + "<>'N')";
                            break;

                        case "AP":
                            strGroup = string.Format("{0:00}", CvtFunc.ToInt(drGroup["apSecurGrp"]));
                            strMenuSql+= " or (MenuID like '" + ModuleInfo.StrModule.AP + "' and Permit" + strGroup + "<>'N')";
                            break;

                        case "AR":
                            strGroup = string.Format("{0:00}", CvtFunc.ToInt(drGroup["arSecurGrp"]));
                            strMenuSql+= " or (MenuID like '" + ModuleInfo.StrModule.AR + "' and Permit" + strGroup + "<>'N')";
                            break;

                        case "OE":
                            strGroup = string.Format("{0:00}", CvtFunc.ToInt(drGroup["oeSecurGrp"]));
                            strMenuSql+= " or (MenuID like '" + ModuleInfo.StrModule.OE + "' and Permit" + strGroup + "<>'N')";
                            break;

                        case "IM":
                            strGroup = string.Format("{0:00}", CvtFunc.ToInt(drGroup["imSecurGrp"]));
                            strMenuSql+= " or (MenuID like '" + ModuleInfo.StrModule.IM + "' and Permit" + strGroup + "<>'N')";
                            break;

                        case "PO":
                            strGroup = string.Format("{0:00}", CvtFunc.ToInt(drGroup["poSecurGrp"]));
                            strMenuSql+= " or (MenuID like '" + ModuleInfo.StrModule.PO + "' and Permit" + strGroup + "<>'N')";
                            break;

                        case "RM":
                            strGroup = string.Format("{0:00}", CvtFunc.ToInt(drGroup["rmSecurGrp"]));
                            strMenuSql+= " or (MenuID like '" + ModuleInfo.StrModule.RM + "' and Permit" + strGroup + "<>'N')";
                            break;

                        case "TW":
                            strGroup = string.Format("{0:00}", CvtFunc.ToInt(drGroup["twSecurGrp"]));
                            strMenuSql+= " or (MenuID like '" + ModuleInfo.StrModule.TW + "' and Permit" + strGroup + "<>'N')";
                            break;

                        case "TP":
                            strGroup = string.Format("{0:00}", CvtFunc.ToInt(drGroup["tpSecurGrp"]));
                            strMenuSql+= " or (MenuID like '" + ModuleInfo.StrModule.TP + "' and Permit" + strGroup + "<>'N')";
                            break;

                        case "ES":
                            strGroup = string.Format("{0:00}", CvtFunc.ToInt(drGroup["smSecurGrp"]));
                            strMenuSql+= " or (MenuID like '" + ModuleInfo.StrModule.ES + "' and Permit" + strGroup + "<>'N')";
                            break;

                        case "MF":
                            strGroup = string.Format("{0:00}", CvtFunc.ToInt(drGroup["mfSecurGrp"]));
                            strMenuSql+= " or (MenuID like '" + ModuleInfo.StrModule.MF + "' and Permit" + strGroup + "<>'N')";
                            break;

                        default:       // user defined menu          key like "UserMenu%"
                            strUserMenuSql+= " or UserMenuNo=" + (nodeSel.Name.ToString().Substring(8));
                            break;
                    }
                }
                nodeSel = nodeSel.NextNode;
            }
            
            if (strMenuSql != string.Empty)
            {
                strMenuSql = " where " + strMenuSql.Substring(strMenuSql.Length - (strMenuSql.Length - 4));
                strMenuSql = "select MenuID,MenuName,IconName from mMenu" + strMenuSql + " and notused=0 AND IsWholesale=1 AND ProgStatus='D' and Visible=1 order by MenuID";
                dtMenu = dBAccess.GetDataTable(strMenuSql);
                intTotal = dtMenu.Rows.Count;
            }

            if (strUserMenuSql != string.Empty)
            {
                strUserMenuSql = " where (" + strUserMenuSql.Substring(strUserMenuSql.Length - (strUserMenuSql.Length - 4)) + " ) and UserName='" + SysVar.UserName + "'";
                strUserMenuSql = "select UserMenuNo,UserMenuID,MenuID,MenuName from mUserMenu" + strUserMenuSql + " order by UserMenuNo,UserMenuID";
                dtUserMenu = dBAccess.GetDataTable(strUserMenuSql);
                intTotal = dtUserMenu.Rows.Count + intTotal;
            }
            
            pgbMain.Value = pgbMain.Minimum;
            pgbMain.Visible = true;
            pgbMain.Refresh();
            pgbMain.Maximum = intTotal + 10;
            pgbMain.Value = 5;

            TreeNode[] tnArr = null;
            TreeNode tn = null;
    
            // create default menu tree            key start as "D"
            if (strMenuSql != string.Empty)
            {
                foreach (DataRow drMenu in dtMenu.Rows)
                {
                    if (drMenu["MenuId"].ToString().Substring(drMenu["MenuId"].ToString().Length - 9) == "000000000")
                    {
                        strKey = "D" + drMenu["MenuId"].ToString().Trim().Substring(0, 3);
                        nodX = tvObject.Nodes.Add(strKey, drMenu["MenuName"].ToString().Trim(), drMenu["IconName"].ToString().Trim(), drMenu["IconName"].ToString().Trim());
                        nodX.Tag = drMenu["MenuId"].ToString().TrimEnd();
                    }
                    else
                    {
                        strKey = "D" + drMenu["MenuId"].ToString().Trim();
                        if (strKey.Substring(strKey.Length - 6) == "000000") strKey = strKey.Substring(0, 7);
                        if (strKey.Substring(strKey.Length - 3) == "000") strKey = strKey.Substring(0, 10);
                        if (tvObject.Nodes.Find(strKey.Substring(0, strKey.Length - 3), true) != null) //???
                        {
                            tnArr = tvObject.Nodes.Find(strKey.Substring(0, strKey.Length - 3), true);
                            if (tnArr.Length != 0)
                            {
                                tn = tnArr[0];
                                nodX = tn.Nodes.Add(strKey, drMenu["MenuName"].ToString().Trim(), drMenu["IconName"].ToString().Trim(), drMenu["IconName"].ToString().Trim());
                                nodX.Tag = drMenu["MenuId"].ToString().TrimEnd();
                            }
                        }
                    }
                    pgbMain.Value += 1;
                }
            }
            
            // create user menu tree               key start as "N*****U"   N***** means user menu no
            if (strUserMenuSql != string.Empty)
            {
                strMenuSql = "select MenuID,IconName,NotUsed from mMenu where MenuID in " +
                        "(select MenuID from mUserMenu where UserName='" + SysVar.UserName + "')";
                dvMenu = dBAccess.GetDataTable(strMenuSql).DefaultView;

                foreach (DataRow drUserMenu in dtUserMenu.Rows)
                {
                    dvMenu.RowFilter = "MenuID='" + drUserMenu["MenuID"].ToString() + "'";
                    if (dvMenu.Count > 0)
                    {
                        if (!CvtFunc.ToBoolean(dvMenu[0]["NotUsed"]))
                        {
                            if (drUserMenu["UserMenuID"].ToString().Substring(drUserMenu["UserMenuID"].ToString().Length - 9) == "000000000")
                            {
                                strKey = "N" + string.Format("{0:00000}", CvtFunc.ToInt(drUserMenu["UserMenuNo"])) + "U" + drUserMenu["UserMenuID"].ToString().Trim().Substring(0, 3);
                                nodX = tvObject.Nodes.Add(strKey, drUserMenu["MenuName"].ToString().Trim(), dvMenu[0]["IconName"].ToString().Trim(), dvMenu[0]["IconName"].ToString().Trim());
                                nodX.Tag = drUserMenu["MenuId"].ToString().TrimEnd();
                            }
                            else
                            {
                                strKey = "N" + string.Format("{0:00000}", CvtFunc.ToInt(drUserMenu["UserMenuNo"])) + "U" + drUserMenu["UserMenuID"].ToString().Trim();
                                if (strKey.Substring(strKey.Length - 6) == "000000") strKey = strKey.Substring(0, 13);
                                if (strKey.Substring(strKey.Length - 3) == "000") strKey = strKey.Substring(0, 16);
                                if (tvObject.Nodes.Find(strKey.Substring(0, strKey.Length - 3), true) != null)
                                {
                                    tnArr = tvObject.Nodes.Find(strKey.Substring(0, strKey.Length - 3), true);
                                    if (tnArr.Length != 0)
                                    {
                                        tn = tnArr[0];
                                        nodX = tn.Nodes.Add(strKey, drUserMenu["MenuName"].ToString().Trim(), dvMenu[0]["IconName"].ToString().Trim(), dvMenu[0]["IconName"].ToString().Trim());
                                        nodX.Tag = drUserMenu["MenuId"].ToString().TrimEnd();
                                    }
                                }
                            }
                        }
                    }
                    pgbMain.Value+= 1;
                }
            }
            pgbMain.Value = pgbMain.Maximum;
            pgbMain.Visible = false;
        }
        private bool Chk_ItemCanbeChecked(string strKey)
        {
            // Function: check a item in ivwOpiton can be checked ,
            // if this item chenked by aother iveoption , it can not be checked , return False
            bool bChecked = true;
            int intOther = 0;
            TreeNode nodeX = null;
            intOther = (mintPicdownIndex == 0 ? 1 : 0);

            nodeX = FirstNode(GetOptionTreeView(intOther));
            while (nodeX != null)
            {
                if (nodeX.Name.ToString().Trim().ToUpper() == strKey.Trim().ToUpper())
                {
                    if (tvOption0.Nodes[strKey].Checked)
                        bChecked = false;
                    else
                        bChecked = true;

                    break;
                }
                nodeX = nodeX.NextNode;
            }
            return bChecked;
        }
        private TreeView GetOptionTreeView(int iIndex)
        {
            TreeView tvReturn = null;

            if (iIndex == 1)
                tvReturn = tvOption1;
            else
                tvReturn = tvOption0;

            return tvReturn;
        }
        private TreeView GetOptionTreeView()
        {
            return GetOptionTreeView(mintPicdownIndex);
        }
        private Control GetStyleEditControl()
        {
            TextBox txtReturn = null;

            if (mintPicdownIndex == 1)
                txtReturn = txtEdit;
            else
                txtReturn = txtStyle;

            return txtReturn;
        }
        private void DeleteUserMenu()
        {

            WP.MF.DataAccess.MUserMenuDAL mDal = new MUserMenuDAL();
            if (MsgBoxEx.Show(DataFunctions.GetMsg(this.Name, "MSG_WantToDelete", new string[] { mstrSaveName }), DataFunctions.GetMsg(this.Name, "MSG_Delete"), MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)
            {
                mDal.DelUsermenu(mstrSaveName);
                Create_tvOption();
                if (tvEdit.Nodes.Count > 0) tvEdit.Nodes.Clear();
                txtEdit.Text = string.Empty;
                mstrSaveName = string.Empty;
                mblnChange = false;
            }
        }

        private void Order_DragDropTree(TreeNode dragNode)
        {
            // Function: drag source is tveEdit self , order by Nodes
            TreeNode endNode = null;
            string strKey = string.Empty;
            string strSelKey = string.Empty;
            
            #region check can drag drop
            switch (mInsertNodePos)
            {
                case InsertNodePos.NodeStart:
                case InsertNodePos.NodeEnd:
                    if (!ChkCanDragDrop(tvEdit.SelectedNode, FirstNode(tvEdit), null))
                    {
                        MsgBoxEx.Show(DataFunctions.GetMsg(this.Name, "MSG_ThisItemHasExisted"), SysVar.WarnTitle);
                        return;
                    }
                    break;
                case InsertNodePos.NodePrev:
                case InsertNodePos.NodeNext:
                    if (!ChkCanDragDrop(tvEdit.SelectedNode, dragNode, null))
                    {
                        MsgBoxEx.Show(DataFunctions.GetMsg(this.Name, "MSG_ThisItemHasExisted"), SysVar.WarnTitle);
                        return;
                    }
                    break;
                case InsertNodePos.NodeSelf:
                    if (!ChkCanDragDrop(tvEdit.SelectedNode, dragNode.Nodes[0], null))
                    {
                        MsgBoxEx.Show(DataFunctions.GetMsg(this.Name, "MSG_ThisItemHasExisted"), SysVar.WarnTitle);
                        return;
                    }
                    break;
                default:
                    break;
            }
            
            if (dragNode == null)
                if (mInsertNodePos != InsertNodePos.NodeEnd) return;
            else
                if (dragNode.Name == tvEdit.SelectedNode.Name) return;
            
            strSelKey = tvEdit.SelectedNode.Name;
            endNode = CurNodeLastSon(tvEdit, tvEdit.SelectedNode);
            if (tvCopySelf.Nodes.Count > 0) tvCopySelf.Nodes.Clear();
            CopyTreeToTree(tvEdit, tvEdit.SelectedNode, endNode, tvCopySelf, null, string.Empty);
            #endregion
            #region add in end
            if (mInsertNodePos == InsertNodePos.NodeEnd)
            {
                tvEdit.Nodes.Remove(tvEdit.Nodes[strSelKey]);
                CopyTreeToTree(tvCopySelf, tvCopySelf.Nodes[strSelKey], endNode, tvEdit, null, string.Empty);
                tvCopySelf.Nodes.Clear();
                return;
            }
            #endregion
            #region add in one select self , will be a son
            if (mInsertNodePos == InsertNodePos.NodeSelf)
            {
                if (ChkParent(tvCopySelf.Nodes[strSelKey], dragNode))
                {
                    tvEdit.Nodes.Remove(tvEdit.Nodes[strSelKey]);
                    CopyTreeToTree(tvCopySelf, tvCopySelf.Nodes[strSelKey], endNode, tvEdit, dragNode, string.Empty);
                }
                else
                    MsgBoxEx.Show(DataFunctions.GetMsg(this.Name,"MSG_CanNotDoThis"), SysVar.WarnTitle);

                tvCopySelf.Nodes.Clear();
                return;
            }
            #endregion
            #region add in start
            if (mInsertNodePos == InsertNodePos.NodeStart)
            {
                tvEdit.Nodes.Remove(tvEdit.Nodes[strSelKey]);
                CopyTreeToTree(tvEdit, FirstNode(tvEdit), LastNode(tvEdit), tvCopy, null, string.Empty);
                tvEdit.Nodes.Clear();
                CopyTreeToTree(tvCopySelf, tvCopySelf.Nodes[strSelKey], endNode, tvEdit, null, string.Empty);
                CopyTreeToTree(tvCopy, FirstNode(tvCopy), LastNode(tvCopy), tvEdit, null, string.Empty);
                tvCopy.Nodes.Clear();
                tvCopySelf.Nodes.Clear();
                return;
            }
            #endregion
            #region add in one node previous
            if (mInsertNodePos == InsertNodePos.NodePrev)
            {
                if (dragNode.Parent == null)     // has no parent  , is root , no need ckeck
                {
                    tvEdit.Nodes.Remove(tvEdit.Nodes[strSelKey]);
                    CopyTreeToTree(tvEdit, dragNode, CurNodeLastSon(tvEdit, dragNode.LastNode), tvCopy, null, string.Empty);
                    DelCurNode(tvEdit, dragNode);
                    CopyTreeToTree(tvCopySelf, tvCopySelf.Nodes[strSelKey], endNode, tvEdit, null, string.Empty);
                    CopyTreeToTree(tvCopy, FirstNode(tvCopy), LastNode(tvCopy), tvEdit, null, string.Empty);
                    tvCopy.Nodes.Clear();
                }
                else
                {
                    strKey = dragNode.Parent.Name;
                    if (ChkParent(tvCopySelf.Nodes[strSelKey], dragNode.Parent))
                    {
                        tvEdit.Nodes.Remove(tvEdit.Nodes[strSelKey]);
                        CopyTreeToTree(tvEdit, dragNode, CurNodeLastSon(tvEdit, dragNode.LastNode), tvCopy, null, string.Empty);
                        DelCurNode(tvEdit, dragNode);
                        CopyTreeToTree(tvCopySelf, tvCopySelf.Nodes[strSelKey], endNode, tvEdit, tvEdit.Nodes[strKey], string.Empty);
                        CopyTreeToTree(tvCopy, FirstNode(tvCopy), LastNode(tvCopy), tvEdit, tvEdit.Nodes[strKey], string.Empty);
                        tvCopy.Nodes.Clear();
                    }
                    else
                        MsgBoxEx.Show(DataFunctions.GetMsg(this.Name,"MSG_CanNotDoThis"), SysVar.WarnTitle);
                }
                tvCopySelf.Nodes.Clear();
                return;
            }
            #endregion
            #region add in one node next
            if (mInsertNodePos == InsertNodePos.NodeNext)
            {
                if (dragNode.Parent == null)             // has no parent  , is root , no need ckeck
                {
                    tvEdit.Nodes.Remove(tvEdit.Nodes[strSelKey]);
                    if (dragNode.NextNode == null)
                        CopyTreeToTree(tvCopySelf, tvCopySelf.Nodes[strSelKey], endNode, tvEdit, null, string.Empty);
                    else
                    {
                        CopyTreeToTree(tvEdit, dragNode.NextNode, CurNodeLastSon(tvEdit, dragNode.LastNode), tvCopy, null, string.Empty);
                        DelCurNode(tvEdit, dragNode.NextNode);
                        CopyTreeToTree(tvCopySelf, tvCopySelf.Nodes[strSelKey], endNode, tvEdit, null, string.Empty);
                        CopyTreeToTree(tvCopy, FirstNode(tvCopy), LastNode(tvCopy), tvEdit, null, string.Empty);
                        tvCopy.Nodes.Clear();
                    }
                }
                else
                {
                    if (ChkParent(tvCopySelf.Nodes[strSelKey], dragNode.Parent))
                    {
                        tvEdit.Nodes.Remove(tvEdit.Nodes[strSelKey]);
                        if (dragNode.NextNode == null)
                            CopyTreeToTree(tvCopySelf, tvCopySelf.Nodes[strSelKey], endNode, tvEdit, dragNode.Parent, string.Empty);
                        else
                        {
                            CopyTreeToTree(tvEdit, dragNode.NextNode, CurNodeLastSon(tvEdit, dragNode.LastNode), tvCopy, null, string.Empty);
                            DelCurNode(tvEdit, dragNode.NextNode);
                            CopyTreeToTree(tvCopySelf, tvCopySelf.Nodes[strSelKey], endNode, tvEdit, dragNode.Parent, string.Empty);
                            CopyTreeToTree(tvCopy, FirstNode(tvCopy), LastNode(tvCopy), tvEdit, dragNode.Parent, string.Empty);
                            tvCopy.Nodes.Clear();
                        }
                    }
                    else
                        MsgBoxEx.Show(DataFunctions.GetMsg(this.Name, "MSG_CanNotDoThis"), SysVar.WarnTitle);
                }
                tvCopySelf.Nodes.Clear();
            }
            #endregion
        }
        private void Add_DragDropTree(TreeNode dragNode, int intSelAll)
        {
            //Function: add some tree into tvEdit from tvStyle DrogDrop
            //         intSelAll =0 ,copy all , include all sons          
            //         intSelAll<>0 , only copy select item
            string strCopyNo = string.Empty;
            TreeNode endNode = null;
            string strKey = string.Empty;
            
            #region check can drag drop
            switch (mInsertNodePos)
            {
                case InsertNodePos.NodeStart:
                case InsertNodePos.NodeEnd:
                    if (!ChkCanDragDrop(tvStyle.SelectedNode, FirstNode(tvEdit), null))
                    {
                        MsgBoxEx.Show(DataFunctions.GetMsg(this.Name, "MSG_ThisItemHasExisted"), SysVar.WarnTitle);
                        return;
                    }
                    break;
                case InsertNodePos.NodePrev:
                case InsertNodePos.NodeNext:
                    if (!ChkCanDragDrop(tvStyle.SelectedNode, dragNode, null))
                    {
                        MsgBoxEx.Show(DataFunctions.GetMsg(this.Name, "MSG_ThisItemHasExisted"), SysVar.WarnTitle);
                        return;
                    }
                    break;
                case InsertNodePos.NodeSelf:
                    if (!ChkCanDragDrop(tvStyle.SelectedNode, dragNode.Nodes[0], null))
                    {
                        MsgBoxEx.Show(DataFunctions.GetMsg(this.Name, "MSG_ThisItemHasExisted"), SysVar.WarnTitle);
                        return;
                    }
                    break;
                default:
                    break;
            }
            
            strCopyNo = GetNodeCopyNo(tvEdit, tvStyle.SelectedNode.Name);
            if (intSelAll == 0)
                endNode = CurNodeLastSon(tvStyle, tvStyle.SelectedNode);       // select all
            else
                endNode = tvStyle.SelectedNode;                                 // select one
            #endregion
            #region add in end
            if (mInsertNodePos == InsertNodePos.NodeEnd)
            {
                CopyTreeToTree(tvStyle, tvStyle.SelectedNode, endNode, tvEdit, null, strCopyNo);
                return;
            }
            #endregion
            #region add in one select self , will be a son
            if (mInsertNodePos == InsertNodePos.NodeSelf)
            {
                if (ChkParent(tvStyle.SelectedNode, dragNode))
                    CopyTreeToTree(tvStyle, tvStyle.SelectedNode, endNode, tvEdit, dragNode, strCopyNo);
                else
                    MsgBoxEx.Show(DataFunctions.GetMsg(this.Name, "MSG_CanNotDoThis"), SysVar.WarnTitle);

                return;
            }
            #endregion
            #region add in start
            if (mInsertNodePos == InsertNodePos.NodeStart)
            {
                CopyTreeToTree(tvEdit, FirstNode(tvEdit), LastNode(tvEdit), tvCopy, null, string.Empty);
                tvEdit.Nodes.Clear();
                CopyTreeToTree(tvStyle, tvStyle.SelectedNode, endNode, tvEdit, null, strCopyNo);
                CopyTreeToTree(tvCopy, FirstNode(tvCopy), LastNode(tvCopy), tvEdit, null, string.Empty);
                tvCopy.Nodes.Clear();
            }
            #endregion
            #region add in one node previous
            if (mInsertNodePos == InsertNodePos.NodePrev)
            {
                if (dragNode.Parent == null)             // has no parent  , is root , no need ckeck
                {
                    CopyTreeToTree(tvEdit, dragNode, CurNodeLastSon(tvEdit, dragNode.LastNode), tvCopy, null, string.Empty);
                    DelCurNode(tvEdit, dragNode);
                    CopyTreeToTree(tvStyle, tvStyle.SelectedNode, endNode, tvEdit, null, strCopyNo);
                    CopyTreeToTree(tvCopy, FirstNode(tvCopy), LastNode(tvCopy), tvEdit, null, string.Empty);
                    tvCopy.Nodes.Clear();
                }
                else
                {
                    strKey = dragNode.Parent.Name;
                    if (ChkParent(tvStyle.SelectedNode, dragNode.Parent))
                    {
                        CopyTreeToTree(tvEdit, dragNode, CurNodeLastSon(tvEdit, dragNode.LastNode), tvCopy, null, string.Empty);
                        DelCurNode(tvEdit, dragNode);
                        CopyTreeToTree(tvStyle, tvStyle.SelectedNode, endNode, tvEdit, tvEdit.Nodes[strKey], strCopyNo);
                        CopyTreeToTree(tvCopy, FirstNode(tvCopy), LastNode(tvCopy), tvEdit, tvEdit.Nodes[strKey], string.Empty);
                        tvCopy.Nodes.Clear();
                    }
                    else
                        MsgBoxEx.Show(DataFunctions.GetMsg(this.Name, "MSG_CanNotDoThis"), SysVar.WarnTitle);

                }
                return;
            }
            #endregion
            #region add in one node next
            if (mInsertNodePos == InsertNodePos.NodeNext)
            {
                if (dragNode.Parent == null)             // has no parent  , is root , no need ckeck
                {
                    if (dragNode.NextNode == null)
                        CopyTreeToTree(tvStyle, tvStyle.SelectedNode, endNode, tvEdit, null, strCopyNo);
                    else
                    {
                        CopyTreeToTree(tvEdit, dragNode.NextNode, CurNodeLastSon(tvEdit, dragNode.LastNode), tvCopy, null, string.Empty);
                        DelCurNode(tvEdit, dragNode.NextNode);
                        CopyTreeToTree(tvStyle, tvStyle.SelectedNode, endNode, tvEdit, null , strCopyNo);
                        CopyTreeToTree(tvCopy, FirstNode(tvCopy), LastNode(tvCopy), tvEdit, null, string.Empty);
                        tvCopy.Nodes.Clear();
                    }
                }
                else
                {
                    if (ChkParent(tvStyle.SelectedNode, dragNode.Parent))
                    {
                        if (dragNode.NextNode == null)
                            CopyTreeToTree(tvStyle, tvStyle.SelectedNode, endNode, tvEdit, dragNode.Parent, strCopyNo);
                        else
                        {
                            CopyTreeToTree(tvEdit, dragNode.NextNode, CurNodeLastSon(tvEdit, dragNode.LastNode), tvCopy, null, string.Empty);
                            DelCurNode(tvEdit, dragNode.NextNode);
                            CopyTreeToTree(tvStyle, tvStyle.SelectedNode, endNode, tvEdit, dragNode.Parent, strCopyNo);
                            CopyTreeToTree(tvCopy, FirstNode(tvCopy), LastNode(tvCopy), tvEdit, dragNode.Parent, string.Empty);
                            tvCopy.Nodes.Clear();
                        }
                    }
                    else
                        MsgBoxEx.Show(DataFunctions.GetMsg(this.Name, "MSG_CanNotDoThis"), SysVar.WarnTitle);
                }
            }
            #endregion
        }
        private void CopyTreeToTree(TreeView tvSource, TreeNode startNode, TreeNode endNode, 
                TreeView tvObject,  TreeNode CurParent, string strCopyNo)
        {
            // Function: copy some nodes from tvwSource to tvObject ,  between startNode to endNode
            TreeNode nodeSource = null;
            TreeNode nodeX = null;

            tvSource.ImageList = this.iglMenu;
            tvObject.ImageList = this.iglMenu;
            nodeSource = tvSource.Nodes.Find(startNode.Name.ToString(), true)[0];
            
            while (nodeSource.Name != tvSource.Nodes.Find(endNode.Name.ToString(), true)[0].Name)
            {
                if (GetTwoNodeRelation(tvSource, startNode, nodeSource) == "B")          // is brother
                {
                    if (CurParent == null)
                        nodeX = tvObject.Nodes.Add(strCopyNo + nodeSource.Name, nodeSource.Text, nodeSource.ImageKey);
                    else
                        nodeX = tvObject.Nodes[CurParent.Name].Nodes.Add(strCopyNo + nodeSource.Name, nodeSource.Text, nodeSource.ImageKey);
                }
                else      // is not brother   ,  maybe one node son
                    nodeX = tvObject.Nodes.Find(strCopyNo + nodeSource.Parent.Name, true)[0].Nodes.Add(strCopyNo + nodeSource.Name, nodeSource.Text, nodeSource.ImageKey);

                nodeX.Tag = nodeSource.Tag.ToString();
                
                nodeSource = NextNode(tvSource, nodeSource.Name);//(nodeSource.Name)
            }
                
            // add end node
            if (GetTwoNodeRelation(tvSource, startNode, nodeSource) == "B")       // is brother
            {
                if (CurParent == null)
                    nodeX = tvObject.Nodes.Add(strCopyNo + nodeSource.Name, nodeSource.Text, nodeSource.ImageKey);
                else
                    nodeX = tvObject.Nodes[CurParent.Name].Nodes.Add(strCopyNo + nodeSource.Name, nodeSource.Text, nodeSource.ImageKey);
            }
            else          // is not brother   ,  maybe one node son
                nodeX = tvObject.Nodes.Find(strCopyNo + nodeSource.Parent.Name, true)[0].Nodes.Add(strCopyNo + nodeSource.Name, nodeSource.Text, nodeSource.ImageKey);

            nodeX.Tag = nodeSource.Tag.ToString();
            mblnChange = true;
        }
        private string GetNodeCopyNo(TreeView tvObject, string OldKey)
        {
            // Function: get correct node key copy No from tvObject, because maybe some key is equality
            // if key is not same , return ""                      return like C*****
            string strNodeCopyNo = string.Empty;
            TreeNode nodeX = null;
            int intNo = 0;
            int intNo1 = 0;
            
            if (tvObject.Nodes.Count == 0)
            {
                strNodeCopyNo = string.Empty;
                return strNodeCopyNo;
            }
            
            nodeX = FirstNode(tvObject);
            while (nodeX != null)
            {
                if (nodeX.Name.ToString().IndexOf(OldKey) != -1)
                {
                    if (nodeX.Name.ToString().Substring(0, 1) == "C")
                    {
                        intNo1 = CvtFunc.ToInt(nodeX.Name.ToString().Substring(2, 5));
                        if (intNo <= intNo1)
                            intNo = intNo1 + 1;
                    }
                    else
                        if (intNo == 0) intNo = 1;
                }
                nodeX = NextNode(tvObject, nodeX.Name);//(nodeX.Name)
            }
            
            if (intNo == 0)
                strNodeCopyNo = string.Empty;
            else
                strNodeCopyNo = "C" + string.Format("{0:00000}", intNo);

            return strNodeCopyNo;
        }
        private string GetTwoNodeRelation(TreeView tvObject, TreeNode Node1, TreeNode Node2)
        {
            // function: get Node1 and Node2 relation, Node2 is after Node1, this function only use for "coptTreeToTree" function
            string strTwoNodeRelation = "N";           // no relation
            TreeNode nodeX = null;
            
            if (Node1.Name.ToString() == Node2.Name.ToString())
            {
                strTwoNodeRelation = "B";              // is brother
                return strTwoNodeRelation;
            }
            
            nodeX = tvObject.Nodes.Find(Node1.Name.ToString(), true)[0].NextNode;
            while (nodeX != null)
            {
                if (nodeX.Name.ToString() == Node2.Name.ToString())
                {
                    strTwoNodeRelation = "B";           // is brother
                    return strTwoNodeRelation;
                }
                nodeX = nodeX.NextNode;
            }
            return strTwoNodeRelation;
        }
        private InsertNodePos GetInsertPos(TreeNode dragNode, int X, int Y)
        {
            // Function : get insert pos
            InsertNodePos inpInsertPos = InsertNodePos.NodeStart;
            TreeNode nodeX = null;
            int iMod = 0;
            int i = 0;

            if (tvEdit.SelectedNode == null)
            {
                if (tvEdit.Nodes.Count == 0)
                    inpInsertPos = InsertNodePos.NodeEnd;
                else
                {
                    nodeX = FirstNode(tvEdit);
                    while (nodeX != null)
                    {
                        i = i + 1;
                        nodeX = NextVisibleNode(tvEdit, nodeX.Name);
                    }
                    if (Y - GetTreeBeginPos() > intLineHeight * i)
                        inpInsertPos = InsertNodePos.NodeEnd;
                    else
                        inpInsertPos = InsertNodePos.NodeNoPos;
                }
            }
            else
            {
                iMod = BaseFunctions.Mod(Y - GetTreeBeginPos(), intLineHeight);
                if (iMod > 0 && iMod <= intLineHeight / 3)
                {
                    inpInsertPos = InsertNodePos.NodePrev;
                    if (dragNode == FirstNode(tvEdit)) inpInsertPos = InsertNodePos.NodeStart;
                }
                else if (iMod > intLineHeight / 3 && iMod <= intLineHeight * 2 / 3)
                    inpInsertPos = InsertNodePos.NodeSelf;
                else
                    inpInsertPos = InsertNodePos.NodeNext;
            }
            return inpInsertPos;
        }
        private int GetTreeBeginPos()
        {
            return (this.Top + tvEdit.Top + 23);
        }
        private bool ChkCanDragDrop(TreeNode DropNode, TreeNode chkNode, TreeNode speNode)
        {
            //Function:  check tvEdit can drag drop , program will compare DropNode and  all of  chkNode 's brothers(no include speNode)
            //           if DropNode=one of chkNode 's brothers ,  will return False
            //           if DropNode<>all of chkNode 's brothers (no include speNode) ,  will return True
            bool bReturn = true;
            string strSpeKey = string.Empty;
            TreeNode nodeX = null;
            
            if (chkNode == null) return bReturn;

            if (speNode != null) strSpeKey = speNode.Name;

            nodeX = tvEdit.Nodes.Find(chkNode.Name, true)[0];
            while (nodeX != null)
            {
                if (nodeX.Tag.ToString() == DropNode.Tag.ToString())           // Tag is MenuId
                {
                    if (strSpeKey != nodeX.Name)
                    {
                        bReturn = false;
                        break;
                    }
                }
                
                nodeX = tvEdit.Nodes.Find(nodeX.Name, true)[0].NextNode;
            }
            return bReturn;
        }
        private bool ChkParent(TreeNode SourceNode, TreeNode DropNode)
        {
            // Function:check when drag drop ,DropNode menuID is SourceNode menuID parent
            //          return True is parent , otherwise return false
            bool bChkParent = false;
            string strKey = string.Empty;
            string strDropKey = string.Empty;

            if (SourceNode.Name.Substring(0, 1) == "D") // default menu , MenuId save in key
                strKey = SourceNode.Name.Substring(1);
            else                                        // user defined menu , MenuID save in tag
            {
                strKey = SourceNode.Tag.ToString().Substring(SourceNode.Tag.ToString().Length - 12);
                while (strKey.Substring(strKey.Length - 3) == "000")
                {
                    strKey = strKey.Substring(0, strKey.Length - 3);
                }
            }
            
            strDropKey = DropNode.Name;
            if (strDropKey == string.Empty)
            {
                bChkParent = true;
                return bChkParent;
            }
            else
            {
                if (strDropKey.Substring(0, 1) == "C")  // because this item is a copy of menu , it's key like "C*****D******"
                    strDropKey = strDropKey.Substring(6);

                if (strDropKey.Substring(0, 1) == "D")  // default menu , MenuId save in key
                    strDropKey = strDropKey.Substring(1);
                else                                    // user defined menu , MenuID save in tag
                {
                    strDropKey = DropNode.Tag.ToString().Substring(DropNode.Tag.ToString().Length - 12);
                    while (strDropKey.Substring(strDropKey.Length - 3) == "000")
                    {
                        strDropKey = strDropKey.Substring(0, strDropKey.Length - 3);
                    }
                }
            }
            
            if (strKey.Length <= strDropKey.Length)
                bChkParent = false;
            else
            {
                if (strKey.IndexOf(strDropKey) == 0)
                    bChkParent = true;
                else
                    bChkParent = false;
            }

            return bChkParent;
        }
        private TreeNode FirstNode(TreeView tvObject)
        {
            // Function: get tvObject first Node it must be a root
            TreeNode tnFirst = null;
            if (tvObject.Nodes.Count == 0)
                tnFirst = null;
            else
                tnFirst = tvObject.Nodes[0]; //GetOptionTreeView().TopNode;

            return tnFirst;
        }
        private TreeNode LastNode(TreeView tvObject)
        {
            // Function:get  tvObject last Node   it maybe a leaf or root
            TreeNode tnLast = null;
            TreeNode nodeX = null;
            if (tvObject.Nodes.Count == 0)
            {
                tnLast = null;
                return tnLast;
            }

            if (FirstNode(tvObject).Parent == null)
                nodeX = FirstNode(tvObject);
            else
                nodeX = FirstNode(tvObject).Parent.LastNode;

            while (nodeX.Nodes.Count > 0)
            {
                nodeX = nodeX.LastNode;
            }
            tnLast = nodeX;
            return tnLast;
        }
        private TreeNode PreviousNode(TreeView tvObject, string SelKey)
        {
            // Function : get tvObject previous node
            TreeNode tnPrev = null;

            if (tvObject.Nodes[SelKey].PrevNode != null)         // has previous brother
            {
                if (tvObject.Nodes[SelKey].PrevNode.Nodes.Count == 0)
                {
                    tnPrev = tvObject.Nodes[SelKey].PrevNode;    // previous brother has no son
                    return tnPrev;
                }
                else
                {
                    tnPrev = tvObject.Nodes[SelKey].PrevNode.Nodes[0].LastNode;
                    while (tnPrev.Nodes.Count > 0)             // previous brother has son , get last son
                    {
                        tnPrev = tnPrev.Nodes[0].LastNode;
                    }
                    return tnPrev;
                }
            }
            if (tvObject.Nodes[SelKey].Parent == null)            // has no previous brother, and has no parent  , is first one
                tnPrev = null;
            else
                tnPrev = tvObject.Nodes[SelKey].Parent;           // is parent
            return tnPrev;
        }
        private TreeNode NextNode(TreeView tvObject, string SelKey)
        {
            // function: get tvObject next node
            TreeNode tnNext = null;

            if (tvObject.Nodes.Find(SelKey, true)[0] != null && tvObject.Nodes.Find(SelKey, true)[0].Nodes.Count != 0)       // has son
            {
                tnNext = tvObject.Nodes.Find(SelKey, true)[0].Nodes[0];
                return tnNext;
            }
            if (tvObject.Nodes.Find(SelKey, true)[0].NextNode != null)       // has no son , but next brother
                tnNext = tvObject.Nodes.Find(SelKey, true)[0].NextNode;
            else
            {
                if (tvObject.Nodes.Find(SelKey, true)[0].Parent == null)
                {
                    tnNext = null;                             // is last one
                    return tnNext;
                }
                else
                {
                    tnNext = tvObject.Nodes.Find(SelKey, true)[0].Parent;
                    while (tnNext.NextNode == null)
                    {
                        if (tnNext.Parent == null)
                        {
                            tnNext = null;                     // is last one
                            return tnNext;
                        }
                        else
                            tnNext = tnNext.Parent;
                    }
                    tnNext = tnNext.NextNode;                 // is parent's next brother
                }
            }
            return tnNext;
        }
        private TreeNode CurNodeLastSon(TreeView tvObject, TreeNode CurNode)
        {
            // Function: get a current node last son , if this node has no son , return this node
            TreeNode tnLastSon = null;
            tnLastSon = CurNode;
            while (tnLastSon.Nodes.Count > 0)
            {
                tnLastSon = tnLastSon.LastNode;
            }
            return tnLastSon;
        }
        private void DelCurNode(TreeView tvObject, TreeNode startNode)
        {
            // delete after current node all borther only use for "Add_DragDropTree" function
            while (startNode.Name != tvObject.Nodes[startNode.Name].LastNode.Name)
            {
                tvObject.Nodes.Remove(tvObject.Nodes[startNode.Name].LastNode);
            }
            tvObject.Nodes.Remove(tvObject.Nodes[startNode.Name]);
        }
        private TreeNode NextVisibleNode(TreeView tvObject, string SelKey)
        {
            // Function:get a next visible=ture node in tvObject after select node
            TreeNode tnNextVisible = null;
            TreeNode nodeX = null;

            if (tvObject == null || tvObject.Nodes[SelKey] == null)
            {
                tnNextVisible = null;
                return tnNextVisible;
            }

            if (tvObject.Nodes[SelKey].IsExpanded)                 // has sons
            {
                tnNextVisible = tvObject.Nodes[SelKey].Nodes[0];
                return tnNextVisible;
            }
            else
            {
                if (tvObject.Nodes[SelKey].NextNode != null)       // has brother
                {
                    tnNextVisible = tvObject.Nodes[SelKey].NextNode;
                    return tnNextVisible;
                }
            }

            if (tvObject.Nodes[SelKey].Parent == null)        // last boot
                tnNextVisible = null;
            else
            {
                nodeX = tvObject.Nodes[SelKey];
                while (nodeX.Parent.NextNode != null)
                {
                    nodeX = nodeX.Parent;
                    if (nodeX.Parent == null)
                    {
                        tnNextVisible = null;
                        return tnNextVisible;
                    }
                }
                tnNextVisible = nodeX.Parent.NextNode;
            }

            return tnNextVisible;
        }
        #endregion


    }

}